public class Board
{
	char[][][] board;
	int[][][]  state;
	
	int size;
	int zSize;
		
	int[] lastMove;
		
	public Board(int s, int z)
	{		
		size = s;
		zSize = z;				
		
		board = new char[s][s][z];
		state = new int[s][s][z];
						
		lastMove = new int[3];
		lastMove[0] = -1;
		lastMove[1] = 0;
		lastMove[2] = 0;
		
		initalizeBoard();
	}
	
	public Board(Board b)
	{			
		board = new char[b.size][b.size][b.zSize];
		state = new int[b.size][b.size][b.zSize];
		
		for(int x = 0; x < size; x++)
        {
        	for(int y = 0; y < size; y++)
        	{
        		for(int z = 0; z < b.zSize; z++)
	        	{
	        		board[x][y][z] = b.board[x][y][z];
	        		state[x][y][z] = b.state[x][y][z];
	        	}
        	}
        }
        lastMove = new int[3];
        lastMove[0] = b.lastMove[0];
        lastMove[1] = b.lastMove[1];   
        lastMove[2] = b.lastMove[2];
        
        size = b.size;
        zSize = b.zSize;                 
	}
	
	
	public void initalizeBoard()
	{
		for(int x = 0; x < size; x++)
        {
        	for(int y = 0; y < size; y++)
        	{
        		for(int z = 0; z < zSize; z++)
        		{
        			board[x][y][z] = 'o';
        		}
        	}
        }
        
        
        
        if(zSize == 1)
        {
        	int m = size/2;
        	board[m][m][0] = 'g';
			board[m-1][m-1][0] = 'g';
			
			board[m][m-1][0] = 'b';
			board[m-1][m][0] = 'b';
        }
       	else
       	{
       		int m = size/2;
	       	board[m-1]	[m]		[m-1] = 'g';
			board[m]	[m-1]	[m-1] = 'g';
			board[m-1]	[m-1]	[m] = 'g';
			board[m]	[m]		[m] = 'g';
			
			board[m-1]	[m-1]	[m-1] = 'b';
			board[m]	[m]		[m-1] = 'b';
			board[m-1]	[m]		[m] = 'b';
			board[m]	[m-1]	[m] = 'b';	
		}	        
    }
    
    public int[][][] getState()
    {
    	for(int x = 0; x < size; x++)
        {
        	for(int y = 0; y < size; y++)
        	{
        		for(int z = 0; z < zSize; z++)
        		{
        			switch(board[x][y][z])
        			{
        				case 'o':	state[x][y][z] = 0;
        							break;
        				case 'g':	state[x][y][z] = -1;
        							break;
        				case 'b':	state[x][y][z] = 1;
        							break;
        				case 'x':	state[x][y][z] = 0;
        							break;
        				default :	state[x][y][z] = 0;
        							break;
        							
        			}
        		}
        	}
        }
        return state;
    }
    
    public int[][] getState2D()
    {
    	int[][] state2D = new int[size][size];
    	for(int x = 0; x < size; x++)
        {
        	for(int y = 0; y < size; y++)
        	{
        		switch(board[x][y][0])
        		{
        			case 'o':	state2D[x][y] = 0;
        						break;
        			case 'g':	state2D[x][y] = -1;
        						break;
        			case 'b':	state2D[x][y] = 1;
        						break;
        			case 'x':	state2D[x][y] = 0;
        						break;
        			default :	state2D[x][y] = 0;
        						break;
        		}
        	}
        }
        return state2D;
    }
    
    public int[] lastMove2D()
    {
    	int[] lMove = new int[2];
    	lMove[0] = lastMove[0];
    	lMove[1] = lastMove[1];
    	
    	return lMove;
    }
    
    public char boardAt(int x, int y, int z)
    {
    	return board[x][y][z];
    }
    
    public void highlight(int x, int y, int z)
    {
    	board[x][y][z] = 'x';
    }
    
    public boolean makeMove(int x, int y, int z, char p)
    {    	    	   	
    	if(validMove(p, x, y, z))
		{
			lastMove[0] = x;
			lastMove[1] = y;
			lastMove[2] = z;
			place(p, x, y, z);
			return true;
		}		
		return false;
    }
    
    public boolean validMove(char p, int _x, int _y, int _z)
	{	
		boolean valid = false;
		if(board[_x][_y][_z] == 'o' || board[_x][_y][_z] == 'x' )
		{
			for(int i = -1; i <= 1; i++)
        	{
	        	for(int j = -1; j <= 1; j++)
	        	{
	        		for(int k = -1; k <= 1; k++)
	        		{
						boolean gotOne = false;
						
						//System.out.println("checking "+i+", "+j+", "+k); 
						
						int x = _x + i;
						int y = _y + j;
						int z = _z + k;
						
						while(x >= 0 && y >= 0 && z >= 0 && x < size && y < size && z < zSize)
						{
							if(!gotOne && board[x][y][z] != p && board[x][y][z] != 'o' && board[x][y][z] != 'x' )
							{
								gotOne = true;
							}
							else if(gotOne && (board[x][y][z] == 'o' || board[x][y][z] == 'x') )
							{
								break;
							}
							else if(gotOne && board[x][y][z] == p)
							{
								valid = true;
							}
							
							if (!gotOne)
								break;
							
							x += i;
							y += j;
							z += k;
						}
						//System.out.println(valid);
					}
				}
			}			
		}				
		return valid;
	}
	
	public boolean isFull()
	{
		for(int x = 0; x < size; x++)
		{
			for(int y = 0; y < size; y++)
			{
				for(int z = 0; z < zSize; z++)
        		{
					if(board[x][y][z] != 'g' && board[x][y][z] != 'b')
					{
						return false;
					}
				}
			}
		}
		return true;
	}
	
	public int count(int turn)
	{
		int total = 0;
		char p;
		
		if(turn == 1)
			p = 'g';
		else
			p = 'b';
		
		for(int x = 0; x < size; x++)
		{
			for(int y = 0; y < size; y++)
			{
				for(int z = 0; z < zSize; z++)
        		{
					if(board[x][y][z] == p)
					{
						total++;
					}
				}
			}
		}
		return total;
	}
	
	public void place(char p, int _x, int _y, int _z)
	{	
		board[_x][_y][_z] = p;
		
		for(int i = -1; i <= 1; i++)
        {
	       	for(int j = -1; j <= 1; j++)
	        {
	        	for(int k = -1; k <= 1; k++)
	        	{
					boolean gotOne = false;
					boolean validDir = false;
										
					int x = _x + i;
					int y = _y + j;
					int z = _z + k;
					
					while(x >= 0 && y >= 0 && z >= 0 && x < size && y < size && z < zSize)
					{
						if(!gotOne && board[x][y][z] != p && board[x][y][z] != 'o' && board[x][y][z] != 'x' )
						{
							gotOne = true;
						}
						else if(gotOne && (board[x][y][z] == 'o' || board[x][y][z] == 'x') )
						{
							validDir = false;
							break;
						}
						else if(gotOne && board[x][y][z] == p)
						{
							validDir = true;
							break;
						}
						
						if (!gotOne)
						{
							validDir =  false;
							break;
						}
							
						x += i;
						y += j;
						z += k;
					}
					
					x = _x + i;
					y = _y + j;
					z = _z + k;
					
					while(validDir && x >= 0 && y >= 0 && z >= 0 && x < size && y < size && z < zSize)
					{
						//System.out.println("flipping");
						if(board[x][y][z] != p && board[x][y][z] != 'o')
							board[x][y][z] = p;
						
						else if(board[x][y][z] == p)
							break;
												
						x += i;
						y += j;
						z += k;
					}					
				}
			}
		}		
	}
	
	public void markMoves(int turn)
	{
		char p;
		
		if(turn == 1)
			p = 'g';
		else
			p = 'b';
			
		for(int x = 0; x < size; x++)
		{
			for(int y = 0; y < size; y++)
			{
				for(int z = 0; z < zSize; z++)
        		{
					if(validMove(p, x, y, z))
					{
						highlight(x, y, z);
					}
				}
			}
		}
	}
	
	public void clearMarks()
	{
		for(int x = 0; x < size; x++)
		{
			for(int y = 0; y < size; y++)
			{
				for(int z = 0; z < zSize; z++)
        		{
					if(board[x][y][z] == 'x')
					{
						board[x][y][z] = 'o';
					}
				}
			}
		}
	}
}